package com.boot2.core.web;

import com.boot2.core.constant.CoreConstant;
import com.boot2.core.dao.PageInfo;
import com.boot2.core.dao.jpa.JpaDynamicSearchHolder;
import com.boot2.core.utils.StringUtils;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.ui.Model;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.ServletContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 请求上下文
 *
 * @author zhangweilin
 * @version V1.0
 * @date 2016年4月19日 下午12:21:55
 * @description
 */
public class RequestContext {

    private final static ThreadLocal<RequestContext> contextThreadLocal = new ThreadLocal<RequestContext>();
    // private ServletContext context;
    private HttpSession session;
    private HttpServletRequest request;
    private HttpServletResponse response;
    private RedirectAttributes redirectAttributes;
    private Map<String, Cookie> cookies;
    private Model model;
    private PageInfo pageInfo;
    private Pageable pageable;


    /**
     * //当前请求的类上下文，比如当前请求的处理类,处理方法，接收参数等等
     */
    private Object handler;


    /**
     * @param request
     * @param response
     * @param handler  类的上下文
     * @return
     */
    public static RequestContext start(HttpServletRequest request, HttpServletResponse response, Object handler) {
        RequestContext requestContext = start(request, response);
        requestContext.handler = handler;
        return requestContext;
    }


    /**
     * 初始化请求上下文
     *
     * @param request
     * @param response
     * @return
     */
    public static RequestContext start(HttpServletRequest request, HttpServletResponse response) {
        // 传列表搜索时的操作符，比如appDeviceSn:like,appCode:like,id:<=,createTime:between
        String searchOp = request.getParameter(CoreConstant.op);
//        request.setAttribute(CoreConstant.searchOpRequestAttibuteKey, searchOp);
        JpaDynamicSearchHolder.set(searchOp);

        //由客户端动态改变国家语言
//        前台所有接口传一个语言参数值到后台完成国际化功能。
//        可以在所有header中传 lang=en_US
//        也可以直接xxx?lang=en_US
        String lang = request.getHeader("lang");
        if (StringUtils.isEmptyString(lang)) {
            lang = request.getParameter("lang");
        }
        if (StringUtils.isNotEmpty(lang)) {
            String[] langArr = lang.split("_");
            if (langArr != null && langArr.length == 2) {
                Locale local = new Locale(langArr[0], langArr[1]);
                LocaleContextHolder.setLocale(local, true);
            }
        }

        RequestContext requestContext = new RequestContext();
        // requestContext.context = servletContext;
        requestContext.request = request;
        requestContext.response = response;
        requestContext.session = request.getSession();
        requestContext.cookies = new HashMap<String, Cookie>();
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie ck : cookies) {
                requestContext.cookies.put(ck.getName(), ck);
            }
        }
        contextThreadLocal.set(requestContext);
        // System.out.println("在RequestContext.start中,pageNo: " +
        // request.getParameter("pageNo"));
        return requestContext;
    }


    public void setHandler(Object handler) {
        this.handler = handler;
    }

    /**
     * 获取当前请求的上下文
     *
     * @return
     */
    public static RequestContext get() {
        return contextThreadLocal.get();
    }

    public static HttpSession getSession() {
        RequestContext requestContext = get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getSession();
    }

    public static HttpServletRequest getRequest() {
        RequestContext requestContext = get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getRequest();
    }

    public static void setRequest(HttpServletRequest request) {
        RequestContext requestContext = get();
        if (requestContext != null) {
            requestContext._setRequest(request);
        }
    }

    private void _setRequest(HttpServletRequest request) {
        this.request = request;
    }

    public static void setResponse(HttpServletResponse response) {
        RequestContext requestContext = get();
        if (requestContext != null) {
            requestContext._setResponse(response);
        }
    }

    private void _setResponse(HttpServletResponse response) {
        this.response = response;
    }

    public static Object getHandler() {
        RequestContext requestContext = get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getHandler();
    }

    public static HttpServletResponse getResponse() {
        RequestContext requestContext = get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getResponse();
    }

    public static Map<String, Cookie> getCookies() {
        RequestContext requestContext = get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getCookies();
    }

    public static Model getModel() {
        RequestContext requestContext = get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getModel();
    }

    public void setModel(Model model) {
        RequestContext requestContext = contextThreadLocal.get();
        if (requestContext == null) {
            return;
        }
        requestContext._setModel(model);
        contextThreadLocal.set(requestContext);
    }

    public static RedirectAttributes getRedirectAttributes() {
        RequestContext requestContext = get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getRedirectAttributes();
    }

    public void setRedirectAttributes(RedirectAttributes redirectAttributes) {
        RequestContext requestContext = contextThreadLocal.get();
        if (requestContext == null) {
            return;
        }
        requestContext._setRedirectAttributes(redirectAttributes);
        contextThreadLocal.set(requestContext);
    }

    public static <T> PageInfo<T> getPageInfo() {
        RequestContext requestContext = contextThreadLocal.get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getPageInfo();
    }

    public void setPageInfo(PageInfo<?> pageInfo) {
        RequestContext requestContext = contextThreadLocal.get();
        if (requestContext == null) {
            return;
        }
        requestContext._setPageInfo(pageInfo);
        requestContext._setPageable(PageRequest.of(pageInfo.getPageNo(), pageInfo.getPageSize()));
        contextThreadLocal.set(requestContext);
    }

    public static Pageable getPageable() {
        RequestContext requestContext = contextThreadLocal.get();
        if (requestContext == null) {
            return null;
        }
        return requestContext._getPageable();
    }

    public static ServletContext getServletContext() {
        return getSession().getServletContext();
    }

    public void clearContext() {
        // this.context = null;
        this.request = null;
        this.response = null;
        this.session = null;
        this.cookies = null;
        this.model = null;
        this.pageInfo = null;
        this.pageable = null;
        this.handler = null;
        contextThreadLocal.remove();
    }

    private HttpSession _getSession() {
        return session;
    }

    private HttpServletRequest _getRequest() {
        return request;
    }

    /**
     * 获取类上下文
     *
     * @return
     */
    private Object _getHandler() {
        return handler;
    }

    private HttpServletResponse _getResponse() {
        return response;
    }

    private Map<String, Cookie> _getCookies() {
        return cookies;
    }

    private Model _getModel() {
        return model;
    }

    private RedirectAttributes _getRedirectAttributes() {
        return redirectAttributes;
    }

    private void _setModel(Model model) {
        this.model = model;
    }

    private void _setRedirectAttributes(RedirectAttributes redirectAttributes) {
        this.redirectAttributes = redirectAttributes;
    }

    private <T> PageInfo<T> _getPageInfo() {
        return pageInfo;
    }

    private void _setPageInfo(PageInfo<?> pageInfo) {
        this.pageInfo = pageInfo;
    }

    private Pageable _getPageable() {
        return pageable;
    }

    private void _setPageable(Pageable pageable) {
        this.pageable = pageable;
    }

    /**
     * 获取 User-Agent
     *
     * @return
     */
    public String getUserAgent() {
        String userAgent = getRequest().getHeader("User-Agent");
        return userAgent;
    }

}
